package be.kuleuven.cs.mop.gui.dialogs;


import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;

import be.kuleuven.cs.mop.app.controllers.Controllers;
import be.kuleuven.cs.mop.app.controllers.UserController;
import be.kuleuven.cs.mop.domain.exceptions.InvalidCurrentUserException;
import be.kuleuven.cs.mop.domain.model.Invitation;
import be.kuleuven.cs.mop.gui.components.ActionButton;
import be.kuleuven.cs.mop.gui.components.SelectionList;
import be.kuleuven.cs.mop.gui.components.Wrapper;
import be.kuleuven.cs.mop.gui.util.Representation;
import be.kuleuven.cs.mop.gui.util.SwingUtils;



/**
 * {@link ActionDialog} for the "Accept/Decline Helper Invitation" use case
 */
public class AcceptDeclineHelperInvitationDialog extends ActionDialog {
	private static final long serialVersionUID = 1L;
	
	
	private Wrapper<SelectionList<Entry>>	accepted;
	private Wrapper<SelectionList<Entry>>	pending;
	
	
	public AcceptDeclineHelperInvitationDialog(final Frame parent,
			final Controllers controllers) {
		super(parent, "Accept/Decline Helper Invitation", controllers);
		final GridBagConstraints gbc = SwingUtils.getGBC();
		
		try {
			accepted	= new Wrapper<SelectionList<Entry>>(
					new SelectionList<Entry>(Entry.wrap(
							getControllers().getControllerUsers()
							.getAcceptedInvitations()), false));
			pending		= new Wrapper<SelectionList<Entry>>(
					new SelectionList<Entry>(Entry.wrap(
							getControllers().getControllerUsers()
							.getPendingInvitations()), false));
			
			update(getControllers().getControllerUsers());
		} catch (final InvalidCurrentUserException e) {
			log(e);
			dispose();
			return;
		}
		
		gbc.gridx	= 0;
		gbc.gridy	= 0;
		gbc.gridheight	= 2;
		add(pending, gbc);
		
		gbc.gridx	= 1;
		gbc.gridheight	= 1;
		add(new ActionButton("Accept", new Dimension(150, 32), this, "A"), gbc);
		
		gbc.gridy	= 1;
		add(new ActionButton("Decline", new Dimension(150, 32), this, "D"), gbc);
		
		gbc.gridx	= 2;
		gbc.gridy	= 0;
		gbc.gridheight	= 2;
		add(accepted, gbc);
		
		display();
	}
	
	
	
	@Override
	protected void handle(final ActionEvent event) throws Exception {
		try {
			final UserController controller = getControllers().getControllerUsers();
			switch (event.getActionCommand().charAt(0)) {
				case 'A':	//	Accept
					controller.acceptUserInvitation(
							pending.get().getSelection().get(0).get());
					break;
					
				case 'D':	//	Decline
					controller.declineUserInvitation(
							pending.get().getSelection().get(0).get());
					break;
					
				default:	//	should never be reached
					throw new InternalError("Invalid parameter");
			}
			update(controller);
		} catch (final IndexOutOfBoundsException e) {
			log("Please select a pending invitation", Level.WARNING);
		} catch (final InvalidCurrentUserException e) {
			log(e);
		}
	}
	
	protected void update(final UserController controller)
			throws InvalidCurrentUserException {
		accepted.set(new SelectionList<Entry>(
				Entry.wrap(controller.getAcceptedInvitations()), false));
		pending.set(new SelectionList<Entry>(
				Entry.wrap(controller.getPendingInvitations()), false));
		
		invalidate();
		pack();
	}
	
	
	
	
	
	
	
	
	
	
	private static class Entry extends Representation<Invitation> {
		
		public Entry(final Invitation invitation) {
			super(invitation);
		}
		
		
		
		@Override
		public String toString() {
			return String.format("Task (ID %d)", get().getTask().hashCode());
		}
		
		public static List<Entry> wrap(final List<Invitation> invitations) {
			final List<Entry> list = new ArrayList<Entry>();
			for (final Invitation invitation : invitations)
				list.add(new Entry(invitation));
			return list;
		}
		
	}
	
}